home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MPW_TOOL / TOOLS / TOOLS_WI / PERL / OS2 / POPEN.C < prev    next >
Text File  |  1992-01-04  |  5KB  |  238 lines

  1. /* added real/protect mode branch at runtime and real mode version
  2.  * names changed for perl
  3.  * Kai Uwe Rommel
  4.  */
  5.  
  6. /*
  7. Several people in the past have asked about having Unix-like pipe
  8. calls in OS/2.  The following source file, adapted from 4.3 BSD Unix,
  9. uses a #define to give you a pipe(2) call, and contains function
  10. definitions for popen(3) and pclose(3).  Anyone with problems should
  11. send mail to me; they seem to work fine.
  12.  
  13. Mark Towfigh
  14. Racal Interlan, Inc.
  15. ----------------------------------cut-here------------------------------------
  16. */
  17.  
  18. /*
  19.  * The following code segment is derived from BSD 4.3 Unix.  See
  20.  * copyright below.  Any bugs, questions, improvements, or problems
  21.  * should be sent to Mark Towfigh (towfiq@interlan.interlan.com).
  22.  *
  23.  * Racal InterLan Inc.
  24.  */
  25.  
  26. /*
  27.  * Copyright (c) 1980 Regents of the University of California.
  28.  * All rights reserved.  The Berkeley software License Agreement
  29.  * specifies the terms and conditions for redistribution.
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <io.h>
  35. #include <string.h>
  36. #include <process.h>
  37. #include <errno.h>
  38.  
  39. #define INCL_NOPM
  40. #define    INCL_DOS
  41. #include <os2.h>
  42.  
  43. static FILE *dos_popen(const char *cmd, const char *flags);
  44. static int dos_pclose(FILE *pipe);
  45.  
  46. /*
  47.  * emulate Unix pipe(2) call
  48.  */
  49.  
  50. #define    tst(a,b)    (*mode == 'r'? (b) : (a))
  51. #define READH           0
  52. #define WRITEH          1
  53.  
  54. static  int       popen_pid[20];
  55.  
  56. FILE *mypopen(char *cmd, char *mode)
  57. {
  58.     int p[2];
  59.         register myside, hisside, save_stream;
  60.         char *shell = getenv("COMPSPEC");
  61.  
  62.         if ( shell == NULL )
  63.           shell = "C:\\OS2\\CMD.EXE";
  64.  
  65.         if ( _osmode == DOS_MODE )
  66.           return dos_popen(cmd, mode);
  67.  
  68.     if (DosMakePipe((PHFILE) &p[0], (PHFILE) &p[1], 4096) < 0)
  69.                 return NULL;
  70.  
  71.         myside = tst(p[WRITEH], p[READH]);
  72.         hisside = tst(p[READH], p[WRITEH]);
  73.  
  74.     /* set up file descriptors for remote function */
  75.     save_stream = dup(tst(0, 1));        /* don't lose stdin/out! */
  76.         if (dup2(hisside, tst(0, 1)) < 0)
  77.         {
  78.         perror("dup2");
  79.         return NULL;
  80.     }
  81.         close(hisside);
  82.  
  83.     /*
  84.      * make sure that we can close our side of the pipe, by
  85.      * preventing it from being inherited!
  86.      */
  87.  
  88.     /* set no-inheritance flag */
  89.     DosSetFHandState(myside, OPEN_FLAGS_NOINHERIT);
  90.  
  91.     /* execute the command:  it will inherit our other file descriptors */
  92.         popen_pid[myside] = spawnlp(P_NOWAIT, shell, shell, "/C", cmd, NULL);
  93.  
  94.     /* now restore our previous file descriptors */
  95.         if (dup2(save_stream, tst(0, 1)) < 0)   /* retrieve stdin/out */
  96.         {
  97.         perror("dup2");
  98.         return NULL;
  99.     }
  100.         close(save_stream);
  101.  
  102.     return fdopen(myside, mode);        /* return a FILE pointer */
  103. }
  104.  
  105. int mypclose(FILE *ptr)
  106. {
  107.     register f;
  108.         int status;
  109.  
  110.         if ( _osmode == DOS_MODE )
  111.           return dos_pclose(ptr);
  112.  
  113.     f = fileno(ptr);
  114.         fclose(ptr);
  115.  
  116.     /* wait for process to terminate */
  117.     cwait(&status, popen_pid[f], WAIT_GRANDCHILD);
  118.  
  119.     return status;
  120. }
  121.  
  122.  
  123. int pipe(int *filedes)
  124. {
  125.   int res;
  126.  
  127.   if ( res = DosMakePipe((PHFILE) &filedes[0], (PHFILE) &filedes[1], 4096) )
  128.     return res;
  129.  
  130.   DosSetFHandState(filedes[0], OPEN_FLAGS_NOINHERIT);
  131.   DosSetFHandState(filedes[1], OPEN_FLAGS_NOINHERIT);
  132.   return 0;
  133. }
  134.  
  135.  
  136. /* this is the MS-DOS version */
  137.  
  138. typedef enum { unopened = 0, reading, writing } pipemode;
  139.  
  140. static struct
  141. {
  142.     char *name;
  143.     char *command;
  144.     pipemode pmode;
  145. }
  146. pipes[_NFILE];
  147.  
  148. static FILE *dos_popen(const char *command, const char *mode)
  149. {
  150.     FILE *current;
  151.     char name[128];
  152.     int cur;
  153.     pipemode curmode;
  154.  
  155.     /*
  156.     ** decide on mode.
  157.     */
  158.     if(strchr(mode, 'r') != NULL)
  159.         curmode = reading;
  160.     else if(strchr(mode, 'w') != NULL)
  161.         curmode = writing;
  162.     else
  163.         return NULL;
  164.  
  165.     /*
  166.     ** get a name to use.
  167.     */
  168.     strcpy(name, "piXXXXXX");
  169.     Mktemp(name);
  170.  
  171.     /*
  172.     ** If we're reading, just call system to get a file filled with
  173.     ** output.
  174.     */
  175.     if(curmode == reading)
  176.     {
  177.         char cmd[256];
  178.         sprintf(cmd,"%s > %s", command, name);
  179.         system(cmd);
  180.  
  181.         if((current = fopen(name, mode)) == NULL)
  182.             return NULL;
  183.     }
  184.     else
  185.     {
  186.         if((current = fopen(name, mode)) == NULL)
  187.             return NULL;
  188.     }
  189.  
  190.     cur = fileno(current);
  191.     pipes[cur].name = strdup(name);
  192.     pipes[cur].command = strdup(command);
  193.     pipes[cur].pmode = curmode;
  194.  
  195.     return current;
  196. }
  197.  
  198. static int dos_pclose(FILE * current)
  199. {
  200.     int cur = fileno(current), rval;
  201.     char command[256];
  202.  
  203.     /*
  204.     ** check for an open file.
  205.     */
  206.     if(pipes[cur].pmode == unopened)
  207.         return -1;
  208.  
  209.     if(pipes[cur].pmode == reading)
  210.     {
  211.         /*
  212.         ** input pipes are just files we're done with.
  213.         */
  214.         rval = fclose(current);
  215.         unlink(pipes[cur].name);
  216.     }
  217.     else
  218.     {
  219.         /*
  220.         ** output pipes are temporary files we have
  221.         ** to cram down the throats of programs.
  222.         */
  223.         fclose(current);
  224.         sprintf(command,"%s < %s", pipes[cur].command, pipes[cur].name);
  225.         rval = system(command);
  226.         unlink(pipes[cur].name);
  227.     }
  228.  
  229.     /*
  230.     ** clean up current pipe.
  231.     */
  232.     free(pipes[cur].name);
  233.     free(pipes[cur].command);
  234.     pipes[cur].pmode = unopened;
  235.  
  236.     return rval;
  237. }
  238.